<template>
  <div class="hello">
    <p>?domain=&user=&port=&password=&transport=</p>
    <div id="config-form" v-show="sipStatus === 0">
      <label>Your Name <input v-model="sipConfig.displayName" type="text" placeholder="John Doe"/></label>
      <label>SIP URI<input v-model="sipConfig.uri" type="text" placeholder="john@example.com"/></label>
      <label>Auth Username<input v-model="sipConfig.authorizationUser" type="text" placeholder="example_john"/></label>
      <label>Password <input v-model="sipConfig.password" type="password"/></label>
      <label>WS Server<input v-model="sipConfig.wsServers" type="text" placeholder="wss://edge.sip.onsip.com"/></label>
      <button @click="createUa"> Create UA </button>
    </div>

    <!-- UA Control Form -->
    <div id="ua" v-show="sipStatus > 0">
      <div v-show="sipStatus >= 2">Connected {{ sipStatus }}</div>
      <button v-show="sipStatus >= 2" @click="unRegister">UnRegister</button>
      <div v-show="sipStatus < 2">DisConnected {{ sipStatus }}</div>
      <button v-show="sipStatus < 2" @click="register">Register</button>
      <div id="new-session-form">
        <label>SIP URI <input v-model="sipTarget" type="text" id="ua-uri"/></label>
        <button id="ua-invite-submit" @click="callPhone" :disabled="sipStatus < 2"> call </button>
      </div>
    </div>

    <ul id="session-list" v-show="sipStatus > 0">
      <li v-for="(session, index) in sessions" :key="index" class="session">
        <h2>
          <strong v-if="'remote' === session.originator">
            {{session.to}}&lt;--{{session.from}}
          </strong>
          <strong v-else>
            {{session.from}}--&gt;{{session.to}}
          </strong>
        </h2>
        <p>
          <button @click="acceptPhone(session.id)">接听</button>
          <button @click="breakPhone(session.id)">挂断</button>
        </p>
        <p>
          <audio :id="'localAudio' + index" style="display:none"></audio>
          <audio :id="'remoteAudio' + index" style="display:none"></audio>
          <video :id="'localVideo' + index" autoplay>Video Disabled or Unavailable</video>
          <video :id="'remoteVideo' + index" autoplay>Video Disabled or Unavailable</video>
        </p>
        <ul class="messages"></ul>
        <form class="message-form" action="">
          <input type="text" placeholder="Type to send a message"/>
          <input type="submit" value="Send"/>
        </form>
      </li>
    </ul>
    <!-- 显示录制的视频 -->
    <video id="videoID" src="" controls autoplay playsinline></video>
  </div>
</template>
<script>
import JsSIP from 'jssip'
// import RecordRTC from 'recordrtc'
import MultiStreamRecorder from 'recordrtc'

JsSIP.debug.enable('JsSIP:*')
const SIP_STATUS = {
  waiting: 0,
  connected: 1,
  registered: 2,
  calling: 3,
  hold: 4
}
let domain = '192.168.20.72'
let user = '1000'
let port = '5066'
let password = '1234'
let transport = 'ws'
export default {
  name: 'HelloWorld',
  data: () => {
    return {
      sipStatus: SIP_STATUS.waiting,
      sipTarget: `${user}@${domain}`,
      sipConfig: {
        displayName: `${user}`,
        uri: `${user}@${domain}`,
        authorizationUser: `${user}`,
        password: password,
        wsServers: `${transport}://${domain}:${port}`
      },
      sessions: []
    }
  },
  mounted() {
    window._myApp = this;
    user = this.getQueryString('user') || '1000'
    transport = this.getQueryString('transport') || 'ws'
    port = this.getQueryString('port') || '5066'
    password = this.getQueryString('password') || '1234'
    domain = this.getQueryString('domain') || '192.168.20.72'
    this.sipTarget = `${user}@${domain}`
    this.sipConfig = {
      displayName: `${user}`,
      uri: `${user}@${domain}`,
      authorizationUser: `${user}`,
      password: password,
      wsServers: `${transport}://${domain}:${port}`
    }
  },
  methods: {
    getQueryString(name) {
      var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
      var r = window.location.search.substr(1).match(reg);
      if (r != null) return unescape(r[2]);
      return null;
    },
    createUa() {
      const socket = new JsSIP.WebSocketInterface(this.sipConfig.wsServers)
      console.log('socket', socket, socket.via_transport)
      const configuration = {
        sockets  : [ socket ],
        outbound_proxy_set: this.sipConfig.wsServers,
        uri : this.sipConfig.uri,
        password : this.sipConfig.password,
        authorizationUser: this.sipConfig.authorizationUser,
        session_timers: false,
        traceSip: false,
        register: false
      }
      const coolPhone = new JsSIP.UA(configuration)
      coolPhone.on('connected', (e) => {
        console.log('connected', e)
        this.sipStatus = SIP_STATUS.connected
      });

      coolPhone.on('disconnected', (e) => {
        console.log('disconnected', e)
        this.sipStatus = SIP_STATUS.waiting
      });

      coolPhone.on('newRTCSession', ({ originator, session, request }) => {
        console.log('newRTCSession', originator, session, request)
        if (originator === 'remote') {
          this.sessions.push({
            id: session.id,
            from: request.from._uri.toString().substr(4),
            to: this.sipConfig.uri,
            originator, session, request
         });
         if(window.Notification && window.Notification.permission !== "denied") {
            window.Notification.requestPermission(() => {
                new Notification('通话呼入', { body: request.from._uri.toString().substr(4) });
            });
          }
        } else {
          this.sessions.push({
            id: session.id,
            from: this.sipConfig.uri,
            to: this.sipTarget,
            originator, session, request
         });
        }

        session.on("confirmed", () => {
          console.log('confirmed', session.connection)
          const index = this.sessions.findIndex(item => {
            return item.session.id === session.id
          });
          const addTrack = (tracks, stream) => {
              console.log('tracks', tracks)
              for (let i = 0; i < tracks.length; i++) {
                stream.addTrack(tracks[i].track);
              }
          }
          const localVideoStream = new MediaStream();
          const localVideo = document.getElementById('localVideo' + index);
          localVideo.srcObject = localVideoStream;
          addTrack(session.connection.getSenders(), localVideoStream);
          localVideo.play();

          const remoteVideoStream = new MediaStream()
          const remoteVideo = document.getElementById('remoteVideo' + index)
          remoteVideo.srcObject = remoteVideoStream
          addTrack(session.connection.getReceivers(), remoteVideoStream)
          remoteVideo.play()

          // 录制视频
          const options = {
            mimeType: 'video/webm'
          }
          const streams = [localVideoStream, remoteVideoStream]
          let recorderNew = new MultiStreamRecorder(streams, options)
          recorderNew.startRecording()
          setTimeout(() => {
            recorderNew.stopRecording(() => {
              // const blob = recorderNew.getBlob()
              const video = document.getElementById('videoID')
              video.src = video.srcObject = null
              video.muted = false
              video.volume = 1
              video.src = URL.createObjectURL(recorderNew.getBlob())
            })
          }, 10000)
        })

        session.on('ended',() => {
          setTimeout(() => { this.breakPhone(session.id) }, 2000)
        });

      });

      coolPhone.on('newMessage', (e) => {
        console.log('newMessage', e)
      });

      coolPhone.on('registered', (e) => {
        console.log('registered', e)
        this.sipStatus = SIP_STATUS.registered
      });
      coolPhone.on('unregistered', (e) => {
        console.log('unregistered', e)
        this.sipStatus = SIP_STATUS.connected
      });
      coolPhone.on('registrationFailed', (e) => {
        console.log('registrationFailed', e)
        this.sipStatus = SIP_STATUS.connected
      });

      coolPhone.start();
      window._sip_ua = coolPhone
    },
    register() {
      window._sip_ua.register();
    },
    unRegister() {
      var options = {
        all: false
      };
      window._sip_ua.unregister(options);
    },
    callPhone() {
      console.log('callPhone', 1)
      if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        console.log('callPhone', 2)
        navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then((stream) => {
          console.log('callPhone', 3)
          var eventHandlers = {
            'progress': function(e) {
              console.log('progress', e)
            },
            'failed': function(e) {
              console.log('failed', e)
            },
            'ended': function(e) {
              console.log('ended', e)
            },
            'confirmed': function(e) {
              console.log('confirmed', e)
            }
          }
          const options = {
            'eventHandlers'    : eventHandlers,
            'mediaConstraints' : { 'audio': true, 'video': true },
            'mediaStream' : stream
          }
          const session = window._sip_ua.call(this.sipTarget, options);
          console.log('call', session)
        });
      }

    },
    acceptPhone(id) {
      const index = this.sessions.findIndex(item => {
        return item.session.id === id
      });
      if (index > -1) {
        const session = this.sessions[index].session;
        navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then((stream) => {
          const options = {
            'mediaConstraints' : { 'audio': true, 'video': true },
            'mediaStream' : stream
          }
          session.answer(options)
        });
      }

    },
    breakPhone(id) {
      console.log('breakPhone', id)
      const session = this.sessions.find(item => {
        return item.session.id === id
      });
      if (session) {
        try {
          session.session.terminate();
        } catch(e) {
          console.error(e)
        }
        const index = this.sessions.findIndex(item => {
          return item.session.id === session.session.id
        })
        this.sessions.splice(index, 1)
      }
    }
  }
}

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
/*** COMPONENT STYLES ***/
input[type='submit'],
button,
button.green {
  background-color: #35f659;
  border: 0px;
  height: 3em;
  cursor: pointer;
}

input[type='text'],
input[type='password'] {
  min-width: 15em;
}

button.red {
  background-color: #ea4b35;
}

label {
  display: block;
  text-align: right;
  margin: 0.5em 0;
}

ul,
li {
  list-style: none;
  padding: 0;
}

/*** STRUCTURE STYLES ***/
h1 {
  display: block;
  text-align: center;
  width: 45%;
  float: left;
  padding: 0 4px;
}

body {
  background: #f5f7f7;
  font-family: sans-serif;
}

#config-form,
#ua {
  float: left;
  clear: left;
  width: 80%;
  padding-right: 15%;
  text-align: right;
  border-radius: 1em;
  border: 4px solid #3f4446;
}

#session-list {
  float: left;
  width: 90%;
  margin: 0 0 0 4%;
}

.session {
  clear: both;
  display: block;
  border: 1px solid red;
  border-radius: 1em;
  border: 4px solid #ea4b35;
  text-align: center;
}

.session h2 {
  font-weight: normal;
}

.session h2 strong {
  font-weight: bold;
}

.session p button {
  margin: 5px 20px;
}

.session p video {
  display: block;
  visibility: none;
  height: 200px;
  width: 45%;
  margin: 0 2%;
  display: inline;
}

.session p video.on {
  visiblity: visible;
  height: auto;
}

.session .messages {
  max-height: 10em;
  min-height: 2em;
  overflow: auto;
}

.session .messages .local {
  color: #5f7ee0;
  clear: left;
  float: right;
  width: 60%;
  text-align: right;
  margin-right: 10%;
}

.session .messages .remote,
.session .messages .error {
  color: #00a53b;
  clear: right;
  float: left;
  width: 60%;
  text-align: left;
  margin-left: 10%;
}

.session .messages .error {
  color: #ea4b35;
}

/*** Old styles ***/

#target {
  width: 25em;
}

#hangup {
  background-color: red;
}

.call-control {
  height: 3em;
}

#dtmf-buttons button {
  display: inline-block;
  margin: 1em 0 0 0;
  height: 3.8em;
  width: 3.8em;
  background-color: white;
  border: 1px solid black;
  border-radius: 2px;
  font-size: 1em;
}

input {
  border-radius: 2px;
  border: 0px;
  height: 3em;
}

input[type='submit'] {
  background-color: #35f659;
  border: 0px;
}

input[type='checkbox'] {
  height: auto;
}

#chat-box {
  position: relative;
  border-radius: 2px;
  border: 1px solid black;
  width: 50em;
  height: 40em;
}

#message-input {
  width: 100%;
  position: absolute;
  bottom: 1em;
  border-top: 1px solid black;
  padding-top: 1em;
}

#message,
#message-submit {
  display: inline-block;
  margin: 0px 0px 0px 0px;
  padding: 1px 1px 1px 1px;
}

#message {
  width: 80%;
  margin-left: 5em;
  border-top-right-radius: 0px;
  border-bottom-right-radius: 0px;
}

#message-submit {
  margin-left: -4px;
  border-top-left-radius: 0px;
  border-bottom-left-radius: 0px;
  padding-left: 5px;
  padding-right: 5px;
}

#log-container {
  height: 35em;
  overflow: scroll;
}

#remote-media {
  border-radius: 2px;
  border: 1px black solid;
}
</style>
